﻿using JT808.Protocol;
using JT808.Protocol.Extensions;
using JT808.Protocol.MessageBody;
using JT808.Protocol;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using JT808.Repository;
using JT808.Repository.Models;
using System.Configuration;

namespace JT808_win
{
    public delegate void JT808NewMsgReceived(JT808Session session, JT808RequestInfo requestInfo);
    //public delegate void JT808NewTerminalLogin(JT808Session session, JT808RequestInfo requestInfo);
    //public delegate void JT808TerminalLogout(JT808Session session, JT808RequestInfo requestInfo);
    public delegate void JT808MsgResponse(JT808Session session, JT808RequestInfo requestInfo, JT808Package responsePackage);
    public class JT808Server : AppServer<JT808Session, JT808RequestInfo>
    {
        public static ServerConfig DefaultConfig = new ServerConfig()
        {
            Name = "SuperSocketServer",
            ServerTypeName = "SuperSocketServer",
            ClearIdleSession = false, //60秒执行一次清理90秒没数据传送的连接
            ClearIdleSessionInterval = 60,
            IdleSessionTimeOut = 90,
            MaxRequestLength = 10000, //最大包长度
            Ip = "Any",
            Port = 6000,
            MaxConnectionNumber = 10000,//最大允许的客户端连接数目
        };
        JT808DataRepository jT808DataRepostiory;
        public event JT808NewMsgReceived JT808NewMsgReceived;
        public event JT808MsgResponse JT808MsgResponse;
        public static Dictionary<string,JT808Session> Sessions { get; set; }
        public JT808Server()
           : base(new DefaultReceiveFilterFactory<JT808Filter, JT808RequestInfo>())
        {
        }

        public override bool Start()
        {
            this.NewRequestReceived += JT808Server_NewRequestReceived;
            //重建所有Session。
            Sessions = new Dictionary<string, JT808Session>();
            jT808DataRepostiory = new JT808DataRepository(ConfigurationManager.ConnectionStrings["JT808"].ConnectionString);
            return base.Start();
        }

        public bool Send8107(string TerminalId)
        {
            var session = GetSession(TerminalId);
            JT808Package jT808Package = new JT808Package
            {
                Header = new JT808Header
                {
                    MsgId = JT808.Protocol.Enums.JT808MsgId.查询终端属性.ToUInt16Value(),
                    //ManualMsgNum = 10,
                    TerminalPhoneNo = "012345678900",
                },
                Bodies = new JT808_0x8107
                {
                }
            };

            //先保存消息日志
            JT808MsgLog log = GetAndSaveMsgLog(session, jT808Package);
            return session.TrySend(new ArraySegment<byte>(log.MsgData));
        }
        private JT808Session GetSession(string TerminalId)
        {
            string sessionId = "";
            return Sessions[sessionId];
        }
        /*
        //连接断开的判断：
        1、TCP连接断开
        2、相同身份终端建立新连接
        3、在一定时间内未收到终端发出的消息（最近心跳超时）
         */
        private void JT808Server_NewRequestReceived(JT808Session session, JT808RequestInfo requestInfo)
        {
            if (JT808NewMsgReceived!=null)
                JT808NewMsgReceived(session,requestInfo);

            int responseStatus = 0;
            JT808Package responsePackage = new JT808Package();

            switch (requestInfo.jT808Package.Header.MsgId)
            {
                case (ushort)JT808.Protocol.Enums.JT808MsgId.位置信息汇报:
                    //平台通用应答
                    CommonResponse(requestInfo, responsePackage);
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端心跳:
                    //平台通用应答
                    //更新最后在线时间
                    CommonResponse(requestInfo, responsePackage);
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端注册:
                    //终端注册应答
                    //JT808Package jT808Package = new JT808Package();
                    responsePackage.Header = new JT808Header
                    {
                        MsgId = JT808.Protocol.Enums.JT808MsgId.终端注册应答.ToUInt16Value(),
                        //ManualMsgNum = 126,
                        TerminalPhoneNo = requestInfo.jT808Package.Header.TerminalPhoneNo
                    };

                    //jT808Package.Header.

                    JT808_0x8100 jT808_0x8100 = new JT808_0x8100();
                    jT808_0x8100.AckMsgNum = requestInfo.jT808Package.Header.MsgNum;
                    jT808_0x8100.Code = Guid.NewGuid().ToString();// "";//鉴权码
                                           //jT808_0x8100.Description = "";
                    jT808_0x8100.JT808TerminalRegisterResult = JT808.Protocol.Enums.JT808TerminalRegisterResult.成功;
                    jT808_0x8100.SkipSerialization = false;
                    responsePackage.Bodies = jT808_0x8100;
                    JT808Terminal id = SaveTerminalInfo(session, requestInfo, responsePackage);

                    jT808_0x8100.Code = id.Code;
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端注销:
                    //todo:
                    CommonResponse(requestInfo, responsePackage);
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端鉴权:
                    var body = (JT808_0x0102)(requestInfo.jT808Package.Bodies);
                    string terminalCode = body.Code;//到数据库里查一下
                    session.TerminalInfo = null;
                    session.TerminalPhoneNo = requestInfo.jT808Package.Header.TerminalPhoneNo;
                    CommonResponse(requestInfo, responsePackage);
                    //通用应答
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端通用应答:
                    //修改对应消息状态
                    JT808_0x0001Process(requestInfo);
                    //不用回复了
                    break;
                default:
                    break;
            }
            saveMsgLog(session, requestInfo, responsePackage, responseStatus);
            //写回复
            SendToSession(responsePackage, session);
            if (JT808MsgResponse != null)
                JT808MsgResponse(session, requestInfo, responsePackage);
            //throw new System.NotImplementedException();
        }
        private int JT808_0x0001Process(JT808RequestInfo requestInfo)
        {
            JT808_0x0001 jT808_0x0001 = (JT808_0x0001)requestInfo.jT808Package.Bodies;
            if(jT808_0x0001.JT808TerminalResult==0)
            switch (jT808_0x0001.MsgId)
            {
                case (ushort)JT808.Protocol.Enums.JT808MsgId.CAN总线数据上传:
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端心跳:
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端注册:
                   
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端注销:
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端鉴权:
                    //通用应答
                    break;
                case (ushort)JT808.Protocol.Enums.JT808MsgId.终端通用应答:
                    //不用回复了
                    break;
                default:
                    break;

            }
            return 0;
        }
            

        public JT808Server(SessionHandler<JT808Session> NewSessionConnected, SessionHandler<JT808Session, SuperSocket.SocketBase.CloseReason> SessionClosed)
            : base(new DefaultReceiveFilterFactory<JT808Filter, JT808RequestInfo>())
        {
            this.NewSessionConnected += NewSessionConnected;
            this.SessionClosed += SessionClosed;
        }
        private static void CommonResponse(JT808RequestInfo requestInfo, JT808Package responsePackage, JT808.Protocol.Enums.JT808PlatformResult result = JT808.Protocol.Enums.JT808PlatformResult.成功)
        {
            responsePackage.Header = new JT808Header
            {
                MsgId = JT808.Protocol.Enums.JT808MsgId.平台通用应答.ToUInt16Value(),
                //ManualMsgNum = 10,
                TerminalPhoneNo = requestInfo.jT808Package.Header.TerminalPhoneNo
            };

            responsePackage.Bodies = new JT808_0x8001
            {
                AckMsgId = requestInfo.jT808Package.Header.MsgId.ToUInt16Value(),
                JT808PlatformResult = result,
                MsgNum = requestInfo.jT808Package.Header.MsgNum
            };
        }

        private JT808Terminal SaveTerminalInfo(JT808Session session, JT808RequestInfo requestInfo, JT808Package responseMsg)
        {
            //同一设备多次注册怎么处理？
            JT808Terminal jT808Terminal = new JT808Terminal();
            JT808_0x0100 regPackage = (JT808_0x0100)requestInfo.jT808Package.Bodies;
            jT808Terminal.AreaID = regPackage.AreaID.ToString();
            jT808Terminal.CityOrCountyId = regPackage.CityOrCountyId.ToString();
            jT808Terminal.Code = "";
            jT808Terminal.MakerId = regPackage.MakerId;
            jT808Terminal.PlateColor = regPackage.PlateColor;
            jT808Terminal.PlateNo = regPackage.PlateNo;
            jT808Terminal.Status = 1;
            jT808Terminal.TerminalId = regPackage.TerminalId;
            jT808Terminal.TerminalModel = regPackage.TerminalModel;
            int id = jT808DataRepostiory.AddJT808Terminal(jT808Terminal);
            jT808Terminal.Code = id.ToString();
            jT808DataRepostiory.UpdateJT808Terminal(jT808Terminal);
            return jT808Terminal;
        }
        //发送消息
        protected bool SendToSession(JT808Package message, JT808Session session)
        {
            session.Send(new ArraySegment<byte>(JT880Tools.JT808Serializer.Serialize(message)));
            //if (appServer != null && appServer.State == SuperSocket.SocketBase.ServerState.Running && !string.IsNullOrEmpty(message))
            //{
            //    foreach (var item in appServer.GetAllSessions())
            //    {
            //        if (item.Connected)
            //        {
            //            var msg = CommandBuilder.BuildMsgCmd(message);
            //            item.Send(msg, 0, msg.Length);
            //        }
            //    }
            //    return true;
            //}
            return false;
        }
        private int saveMsgLog(JT808Session session, JT808RequestInfo requestInfo, JT808Package responseMsg, int responseStatus)
        {

            JT808MsgLog log = new JT808MsgLog();
            log.MsgData = requestInfo.Data;
            log.MsgFrom = false;
            log.MsgId = requestInfo.jT808Package.Header.MsgId;
            log.MsgNum = requestInfo.jT808Package.Header.MsgNum;
            log.MsgTime = DateTime.Now;
            log.PackageIndex = requestInfo.jT808Package.Header.PackageIndex;
            log.PackgeCount = requestInfo.jT808Package.Header.PackgeCount;
            log.ProtocolVersion = requestInfo.jT808Package.Header.ProtocolVersion;
            log.TerminalPhoneNo = requestInfo.jT808Package.Header.TerminalPhoneNo;
            log.ResponseResult = responseStatus;
            log.SessionId = session.SessionID;
            //先保存消息日志
            return jT808DataRepostiory.AddMsgLog(log);
        }

        private JT808MsgLog GetAndSaveMsgLog(JT808Session session, JT808Package jT808Package)
        {
            JT808MsgLog log = new JT808MsgLog();
            log.MsgData = JT880Tools.JT808Serializer.Serialize(jT808Package);
            log.MsgFrom = true;
            log.MsgId = jT808Package.Header.MsgId;
            log.MsgNum = jT808Package.Header.MsgNum;
            log.MsgTime = DateTime.Now;
            log.PackageIndex = jT808Package.Header.PackageIndex;
            log.PackgeCount = jT808Package.Header.PackgeCount;
            log.ProtocolVersion = jT808Package.Header.ProtocolVersion;
            log.TerminalPhoneNo = jT808Package.Header.TerminalPhoneNo;
            log.ResponseResult = -1;
            log.SessionId = session.SessionID;
            //先保存消息日志
            jT808DataRepostiory.AddMsgLog(log);
            return log;
        }


        protected override void OnStarted()
        {
            //启动成功
        }
        protected override void OnNewSessionConnected(JT808Session session)
        {
            try
            {
                //todo:更新状态
                Sessions.Add(session.SessionID, session);
                //session.SessionID
                //连接成功
            }
            catch (Exception ex)
            {

            }

            base.OnNewSessionConnected(session);
        }
        protected override void OnSessionClosed(JT808Session session, CloseReason reason)
        {
            try
            {
                //todo:保存状态
                Sessions.Remove(session.SessionID);
                //把当前Session的所有消息状态修改为超时
            }
            catch (Exception ex)
            {

            }
            base.OnSessionClosed(session, reason);
        }

    }
}
